package com.asia.algorithmcode.fsm;

import java.util.HashMap;
import java.util.Map;

/**
 * @DESCRIPTION:
 * @USER: wanfu
 * @DATE: 2025/3/12 星期三 14:58
 */
public class IsNumber {


    public static void main(String[] args) {
        IsNumber isNumber = new IsNumber();
        System.out.println(isNumber.isNumber("6..3"));
    }

    public boolean isNumber(String s) {
        Map<State, Map<CharType, State>> transfer = new HashMap<>();
        Map<CharType, State> initialMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
            put(CharType.CHAR_SIGN, State.STATE_INT_SIGN);
        }};
        transfer.put(State.STATE_INITIAL, initialMap);

        Map<CharType, State> signMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
        }};
        transfer.put(State.STATE_INT_SIGN, signMap);

        Map<CharType, State> integerMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_POINT, State.STATE_POINT);
            put(CharType.CHAR_EXP, State.STATE_EXP);
        }};
        transfer.put(State.STATE_INTEGER, integerMap);

        Map<CharType, State> pointMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
        }};
        transfer.put(State.STATE_POINT, pointMap);

        Map<CharType, State> pointWithoutIntMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
        }};
        transfer.put(State.STATE_POINT_WITHOUT_INT, pointWithoutIntMap);


        Map<CharType, State> fractionMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
            put(CharType.CHAR_EXP, State.STATE_EXP);
        }};
        transfer.put(State.STATE_FRACTION, fractionMap);

        Map<CharType, State> expMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
        }};
        transfer.put(State.STATE_EXP, expMap);

        Map<CharType, State> expSignMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
        }};
        transfer.put(State.STATE_EXP_SIGN, expSignMap);

        Map<CharType, State> expNumberMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
        }};
        transfer.put(State.STATE_EXP_NUMBER, expNumberMap);

        State strState = State.STATE_INITIAL;
        int n = s.length();

        for (int i = 0; i < n; i++) {
            char ch = s.charAt(i);
            CharType charType = toCharType(ch);
            if (!transfer.get(strState).containsKey(charType)) {
                return false;
            } else {
                strState = transfer.get(strState).get(charType);
            }
        }

        return strState == State.STATE_INTEGER ||
                strState == State.STATE_POINT ||
                strState == State.STATE_FRACTION ||
                strState == State.STATE_EXP_NUMBER ||
                strState == State.STATE_END;
    }

    public CharType toCharType(char ch) {
        if (ch >= '0' && ch <= '9') {
            return CharType.CHAR_NUMBER;
        } else if (ch == 'e' || ch == 'E') {
            return CharType.CHAR_EXP;
        } else if (ch == '.') {
            return CharType.CHAR_POINT;
        } else if (ch == '-' || ch == '+') {
            return CharType.CHAR_SIGN;
        } else {
            return CharType.CHAR_ILLEGAL;
        }
    }

    enum State {
        STATE_INITIAL, // 初始状态
        STATE_INT_SIGN, // 符号
        STATE_INTEGER, // 整数
        STATE_POINT, // 小数点
        STATE_POINT_WITHOUT_INT, // 左侧没有数字的小数点
        STATE_FRACTION, // 小数部分
        STATE_EXP, // 字符e
        STATE_EXP_SIGN, // 指数符号
        STATE_EXP_NUMBER, // 指数数字
        STATE_END // 接受状态
    }

    enum CharType {
        CHAR_NUMBER, // 数字
        CHAR_EXP,//指数
        CHAR_POINT, // 小数点
        CHAR_SIGN, // 正负符号
        CHAR_ILLEGAL // 非法字符
    }

}
